<?php

use Phalcon\Acl;
use Phalcon\Acl\Role;
use Phalcon\Acl\Resource;
use Phalcon\Events\Event;
use Phalcon\Mvc\User\Plugin;
use Phalcon\Mvc\Dispatcher;
use Phalcon\Acl\Adapter\Memory as AclList;

/**
 * SecurityPlugin
 *
 * This is the security plugin which controls that users only have access to the modules they're assigned to
 */
class SecurityPlugin extends Plugin
{

	/**
	 * Returns an existing or new access control list
	 *
	 * @returns AclList
	 */
	public function getAcl()
	{

		//throw new \Exception("something");

		//if (!isset($this->persistent->acl)) {

			$acl = new AclList();

			$acl->setDefaultAction(Acl::DENY);

			//Register roles
			$roles = array(
				'users'  => new Role('Users'),
				'guests' => new Role('Guests'),
				'admin'  => new Role('Admin')
			);
			foreach ($roles as $role) {
				$acl->addRole($role);
			}

			//Admin area resources
			$AdminResources = array(
				'admin'    => array('index', 'setTestBegin', 'setTestClose', 'setTest', 'saveChange', 'saveAdd', "delTest")
			);
			foreach ($AdminResources as $resource => $actions) {
				$acl->addResource(new Resource($resource), $actions);
			}

			//Users area resources
			$UsersResources = array(
				'index'		=> array('reports'),
				'answer'    => array('index', 'reports', 'submit', 'finished', 'closed', 'early')
			);
			foreach ($UsersResources as $resource => $actions) {
				$acl->addResource(new Resource($resource), $actions);
			}

			//Public area resources
			$publicResources = array(
				'index'      => array('index', 'hello'),
				'signup'     => array('index', 'signup'),
				'timer'		 => array('getBeginTime', 'getEndTime'),
				'login'      => array('index', 'login'),
				'logout'     => array('index'),
				'errors'     => array('show404', 'show500','show401')
			);
			foreach ($publicResources as $resource => $actions) {
				$acl->addResource(new Resource($resource), $actions);
			}

			//Grant access to public areas to Users, Guests and Admin
			foreach ($roles as $role) {
				foreach ($publicResources as $resource => $actions) {
					foreach ($actions as $action){
						$acl->allow($role->getName(), $resource, $action);
					}
				}
			}

			//Grant acess to users area to role Users and Admin
			foreach ($UsersResources as $resource => $actions) {
				foreach ($actions as $action){
					$acl->allow('Users', $resource, $action);
					$acl->allow('Admin', $resource, $action);
				}
			}

			//Grant acess to admin area to role Admin
			foreach ($AdminResources as $resource => $actions) {
				foreach ($actions as $action){
					$acl->allow('Admin', $resource, $action);
				}
			}

			//The acl is stored in session, APC would be useful here too
			$this->persistent->acl = $acl;
		//}

		return $this->persistent->acl;
	}

	/**
	 * This action is executed before execute any action in the application
	 *
	 * @param Event $event
	 * @param Dispatcher $dispatcher
	 */
	public function beforeDispatch(Event $event, Dispatcher $dispatcher)
	{
		
		$auth = $this->session->get('auth');

		if (!$auth){
			$role = 'Guests';
		} else {
			if($auth['role'] == 'normal'){
				$role = 'Users';
			}else if($auth['role'] == 'admin'){
				$role = 'Admin';
			}else{
				$role = 'Guests';
			}
			
		}

		$controller = $dispatcher->getControllerName();
		$action = $dispatcher->getActionName();

		$acl = $this->getAcl();
		
		$allowed = $acl->isAllowed($role, $controller, $action);
		if ($allowed != Acl::ALLOW) {
			$dispatcher->forward(array(
				'controller' => 'errors',
				'action'     => 'show404'
			));
			return false;
		}
		
	}
}
